/**
 * Defines Contig table columns
 * Links columns to their corresponding database fields
 * The field mapper for Pairs is in QueryData
 */
package jpave.dataholders;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Vector;
import assem.Utils;

import jpave.query_interface.FieldMapper;
import jpave.query_interface.FieldTab;
import jpave.query_interface.JPaveFrame;
import jpave.query_interface.QueryTab;

import util.data_structures.PrefixTree;
import util.methods.StringHelpers;

public class FilterContigData implements Serializable
{
	private static final boolean debug = false;
	
    public FilterContigData(GlobalSettings settings)
    {
    		// setting set below
    }
	
	public static final int FILTER_NONE = -1;
	public static final int FILTER_OR = 0;
	public static final int FILTER_AND = 1;
	
	public static final int FILTER_INCLUDE = FILTER_AND; 
	public static final int FILTER_EXCLUDE = FILTER_OR;
	
	//*************************************************************************
	// Contig list field IDs.  
	// IMPORTANT: These are saved in the XML preferences file for each user
	//            (located in home/.java/.userPrefs) 
	//            Changing the values will break people's saved preferences
	//				(I think I got this fixed okay)
	//            However, adding new values is okay.
	//*************************************************************************
	// Number in same order as listed on Select columns; columns will display in this order
    public static final int RECORD_NUM_FIELD 		= 900;   
    public static final int CONTIG_ID_FIELD 		= 1000; 
    public static final int TOTAL_EXP_FIELD			= 1001;
    public static final int CONSENSUS_BASES_FIELD 	= 1002;
 
    public static final int NUMBER_EST_FIELD 		= 1003;
    public static final int NUMBER_BURIED_FIELD 	= 1004;	
    public static final int NUMBER_UNBURIED_FIELD 	= 1005;	
    
    public static final int HAS_NS_ID_FIELD 		= 1006;
    public static final int EST_MATE_PAIRS_FIELD 	= 1007;  
    public static final int EST_LONERS_FIELD 		= 1008;  
    public static final int EST_5_PRIME_FIELD 		= 1009;  
    public static final int EST_3_PRIME_FIELD		= 1010;  
      
    public static final int LONGEST_EST_FIELD 		= 1011;	
    public static final int GC_RATIO_FIELD 			= 1012;	
    public static final int NOTES_FIELD				= 1013;
    public static final int PAIRWISE_FIELD			= 1014;
    public static final int SEQ_GROUP				= 1015;
    public static final int SEQ_START				= 1016;
    public static final int SEQ_END					= 1017;
    public static final int SEQ_STRAND				= 1018;
    
    //since # of libraries is dynamic, can only label the start of the range
    // Will add to LIBRARY_COUNT for each library
    public static final int LIBRARY_COUNT_ALL		= 1100;
    public static final int N_LIBRARY_COUNT_ALL		= 1300;
    
    public static final int CONTIG_SET_COUNT = 1900;
    
    public static final int N_FOLD_LIB				= 2700;
    public static final int N_FOLD_LIB_LIMIT		= 2899;
    
    public static final int P_VALUES				= 2900;
    
    public static final int RSTAT_FIELD				= 3000; 
    public static final int RSTAT_INC_FIELD			= 3001;
        
    public static final int SNP_COUNT_FIELD 			= 3002;  
    public static final int SNP_INDEL_FIELD			= 3003;
    
    public static final int FIRST_BEST_UNIPROT_FIELD 		= 3004;
    public static final int FIRST_BEST_DESCRIPTION			= 3005;
    public static final int FIRST_BEST_SPECIES				= 3006;
    public static final int FIRST_BEST_DBTYPE_FIELD		= 3007;
    public static final int FIRST_BEST_TAXO_FIELD			= 3008;
    public static final int FIRST_BEST_EVALUE_FIELD 		= 3009;
    public static final int FIRST_BEST_BIT_SCORE_FIELD 	= 3010;
    public static final int FIRST_BEST_PERCENT_IDENT		= 3011;
    public static final int FIRST_BEST_ALIGN_LEN_FIELD 	= 3012;
    public static final int FIRST_BEST_CTG_START_FIELD		= 3013;
    public static final int FIRST_BEST_CTG_END_FIELD		= 3014;
    public static final int FIRST_BEST_PRO_START_FIELD		= 3015;
    public static final int FIRST_BEST_PRO_END_FIELD		= 3016;
    public static final int FIRST_BEST_KEGG 				= 3017;
    public static final int FIRST_BEST_PFAM 				= 3018;
    public static final int FIRST_BEST_EC 					= 3019;
    
    public static final int OVER_BEST_UNIPROT_FIELD 		= 3020;
    public static final int OVER_BEST_DESCRIPTION			= 3021;
    public static final int OVER_BEST_SPECIES				= 3022;
    public static final int OVER_BEST_DBTYPE_FIELD		= 3023;
    public static final int OVER_BEST_TAXO_FIELD			= 3024;
    public static final int OVER_BEST_EVALUE_FIELD 		= 3025;
    public static final int OVER_BEST_BIT_SCORE_FIELD 	= 3026;
    public static final int OVER_BEST_PERCENT_IDENT		= 3027;
    public static final int OVER_BEST_ALIGN_LEN_FIELD 	= 3028;
    public static final int OVER_BEST_CTG_START_FIELD		= 3029;
    public static final int OVER_BEST_CTG_END_FIELD		= 3030;
    public static final int OVER_BEST_PRO_START_FIELD		= 3031;
    public static final int OVER_BEST_PRO_END_FIELD		= 3032;
    public static final int OVER_BEST_KEGG 				= 3033;
    public static final int OVER_BEST_PFAM 				= 3034;
    public static final int OVER_BEST_EC 				= 3035;
    
    public static final int CNT_TAXO					= 3050;
    public static final int CNT_SPECIES				= 3051;
    public static final int CNT_GENE					= 3052;
    public static final int CNT_OVERLAP				= 3053;
    public static final int CNT_SWISS				= 3054;
    public static final int CNT_TREMBL				= 3055;
    public static final int CNT_NCBI				= 3056;
    public static final int CNT_NT					= 3057;
    
    public static final int ORF_CODING_FRAME 		= 4002;
    public static final int ORF_CODING_LENGTH 		= 4004; 
    public static final int ORF_HAS_START 		= 4007; 
    public static final int ORF_HAS_END 			= 4008; 
    public static final int ORF_START 			= 4009; 
    public static final int ORF_END 				= 4010; 
    
    public static final int PROTEIN_FRAME 	= 5002; 
    public static final int USED_PROTEIN_FRAME 	= 5004; 
 
    public static final String GROUP_NAME_CONTIG 	= "General";
    public static final String GROUP_DESC_CONTIG 	= "General attributes.";

    public static final String GROUP_NAME_SEQ_SET	= "Sequence Set";
    public static final String GROUP_DESC_SEQ_SET	= "Sequences with count libraries";
    
    public static final String GROUP_NAME_LIB		= "Library";
    public static final String GROUP_DESC_LIB		= "Counts and/or RPKM per library";
    
    public static final String GROUP_NAME_NFOLD		= "N-Fold";
    public static final String GROUP_DESC_NFOLD 	    = "Fold change between two libraries";

    public static final String GROUP_NAME_PVAL		= "Differential Expression";
    public static final String GROUP_DESC_PVAL 		= "Columns of DE p-values";
    
    public static final String GROUP_NAME_RSTAT		= "R Statistic";
    public static final String GROUP_DESC_RSTAT		= "The statistic by Stekel et al. (2000) to identify differentially expressed transcripts.";
    
    public static final String GROUP_NAME_CNTS		= "Counts of annoDB Hits";
    public static final String GROUP_DESC_CNTS 		= "Counts of species, minimal overlap, SwissProt, Trembl, NCBI and NT.";
    
    public static final String GROUP_NAME_FIRST_BEST = "Best Eval";
    public static final String GROUP_DESC_FIRST_BEST = "annoDB hit with a good eval (may not be the best if there is one almost as good with a better annotation, see Help).";
    
    public static final String GROUP_NAME_OVER_BEST 	= "Best Annotation";
    public static final String GROUP_DESC_OVER_BEST 	= "annoDB hit with the best annotation (i.e. excluding phrases such as \'uncharacterized protein\', see Help).";
    
    public static final String GROUP_NAME_SNPORF 	= "SNPs and ORFs";
    public static final String GROUP_DESC_SNPORF 	= "Information on SNPs (if assembled) and best ORF.";

    public static final String TABLE_FIRST_BEST 		= "firstbest";
    public static final String TABLE_OVER_BEST			= "overbest";
    public static final String TABLE_FIRST_BEST_DETAIL 	= "firstbestdetail";
    public static final String TABLE_OVER_BEST_DETAIL	= "overbestdetail";
    /**
     * Defines the columns in the Contig Table
     */
    static public FieldMapper createContigFieldMapper (JPaveFrame parentFrame)
    {
    		QueryTab qTab = parentFrame.getQueryTab();
    	
		String [] allLibraryNames = qTab.getAllLibraryNames(false);
		String [] allLibraryTitles = qTab.getAllLibraryTitles(); // CAS 12/28/14
		String [] allContigSetNames = qTab.getAllContigSetNames(false);
		String [] pLabels = qTab.getAllPValNames();	
		String [] pTitles = qTab.getAllPValTitles(); // CAS 12/28/14
			
        FieldMapper mapper = new FieldMapper (allLibraryNames,  allContigSetNames, parentFrame);
   
        // At least one description for each group may be padded with blanks so the display 
        // starting in the same column
        
        // Fields in contig table
        mapper.addRecordNumField ( RECORD_NUM_FIELD, "Seq #", GROUP_NAME_CONTIG, 
        		GROUP_DESC_CONTIG, 
        		"The index of the query result.                                 " );
  
        mapper.addStringField( CONTIG_ID_FIELD, "Seq ID", "contig", "contigid", 
        		GROUP_NAME_CONTIG, GROUP_DESC_CONTIG, 
        		"The sequence identifier." );
        if(allLibraryNames != null && allLibraryNames.length > 0)
	        	mapper.addIntField( TOTAL_EXP_FIELD, "Total Counts", "contig", "totalexp", 
	        		GROUP_NAME_CONTIG, GROUP_DESC_CONTIG, 
	        		"The sum of the counts for all libraries." );
  
        mapper.addIntField( CONSENSUS_BASES_FIELD, "Length", "contig", "consensus_bases", 
        		GROUP_NAME_CONTIG, GROUP_DESC_CONTIG, 
        		"The base length of the sequence." );
        if(parentFrame.hasAssembly()) {
	        mapper.addIntField( NUMBER_EST_FIELD, "#Align", "contig", "numclones", 
	        		GROUP_NAME_CONTIG, GROUP_DESC_CONTIG, 
	        		"The number of aligned reads in the contig." );
        }
        if (parentFrame.hasBuried()) {
			mapper.addIntField( NUMBER_BURIED_FIELD, "#Buried", null, null, 
				GROUP_NAME_CONTIG, GROUP_DESC_CONTIG, 
				"The number of buried sequences in the contig." ); 
			String strNumBuriedQ = "SELECT COUNT(*) FROM contclone WHERE contig.contigid=contclone.contigid and buried=1 ";
			mapper.setFieldSubQuery ( NUMBER_BURIED_FIELD, "numburied", strNumBuriedQ );  
    
			mapper.addIntField( NUMBER_UNBURIED_FIELD, "#Unburied", null, null, 
					GROUP_NAME_CONTIG, GROUP_DESC_CONTIG, 
    			"The number of sequences in the contig that are not buried." ); 
			String strNumUnburiedQ = "SELECT COUNT(*) FROM contclone WHERE contig.contigid=contclone.contigid and buried!=1 ";  
			mapper.setFieldSubQuery ( NUMBER_UNBURIED_FIELD, "numunburied", strNumUnburiedQ );
        }

        if (parentFrame.hasMatePairs()) {
            mapper.addBoolField( HAS_NS_ID_FIELD, "Has Ns", "contig", "has_ns", 
            		GROUP_NAME_CONTIG, GROUP_DESC_CONTIG, 
            		"For mate-pair contigs, they may be joined by 20 Ns" );
	        mapper.addIntField( EST_MATE_PAIRS_FIELD, "#EST Mate Pairs", "contig", "frpairs", 
	        		GROUP_NAME_CONTIG, GROUP_DESC_CONTIG, 
	        		"The number of EST mate-pairs in the contig." );
	        mapper.addIntField( EST_5_PRIME_FIELD, "#EST 5'", "contig", "est_5_prime", 
	        		GROUP_NAME_CONTIG, GROUP_DESC_CONTIG, 
	        		"The number of 5' ESTs in the contig." );
	        mapper.addIntField( EST_3_PRIME_FIELD, "#EST 3'", "contig", "est_3_prime", 
	        		GROUP_NAME_CONTIG, GROUP_DESC_CONTIG, 
	        		"The number of 3' ESTs in the contig." );
        }
        if (parentFrame.hasAssembly()) {
	        mapper.addStringField( LONGEST_EST_FIELD, "Longest", "contig", "longest_clone", 
	        		GROUP_NAME_CONTIG, GROUP_DESC_CONTIG, 
	        		"The identifier for the longest sequence in the contig." );
        }
        
        mapper.addPercentField( GC_RATIO_FIELD, "GC Content", "contig", "gc_ratio", 
        		GROUP_NAME_CONTIG, GROUP_DESC_CONTIG, 
        		"The percent GC content of the sequence." );
        mapper.addStringField( NOTES_FIELD, "Remarks", "contig", "notes", 
        		GROUP_NAME_CONTIG, GROUP_DESC_CONTIG, 
        		"Remarks for a sequence (added with runSingleTCW)." );
        
        if (parentFrame.hasLoc()) {
    	 		mapper.addStringField( SEQ_GROUP, "SeqGroup", "contig", "seq_group", 
	        		GROUP_NAME_CONTIG, GROUP_DESC_CONTIG, 
	        		"The supercontig (scaffold, contig)." );
    	 		mapper.addIntField( SEQ_START, "SeqStart", "contig", "seq_start", 
 	        		GROUP_NAME_CONTIG, GROUP_DESC_CONTIG, 
 	        		"The start position of the predicted gene on the supercontig." );
    	 		mapper.addIntField( SEQ_END, "SeqEnd", "contig", "seq_end", 
 	        		GROUP_NAME_CONTIG, GROUP_DESC_CONTIG, 
 	        		"The end position of the predicted gene on the supercontig." );
    	 		mapper.addStringField( SEQ_STRAND, "SeqStrand", "contig", "seq_strand", 
     	        		GROUP_NAME_CONTIG, GROUP_DESC_CONTIG, 
     	        		"The strand of the predicted gene." );
        }
        
        if (parentFrame.hasPairWise()) {
            mapper.addStringField( PAIRWISE_FIELD, "Pairs Count", "contig", "cnt_pairwise", 
            		GROUP_NAME_CONTIG, GROUP_DESC_CONTIG, 
            		"Number of Similar Sequence Pairs its contain in." );
        }
        
        if(allContigSetNames != null && allContigSetNames.length > 0 && parentFrame.hasAssembly()) {
	        	for(int x=0; x<allContigSetNames.length; x++) { 
	        		mapper.addIntField(CONTIG_SET_COUNT + x, "#" + allContigSetNames[x], "contig", 
	        				"L__" + allContigSetNames[x], GROUP_NAME_SEQ_SET, GROUP_DESC_SEQ_SET, 
	        				"Sequence set " + allContigSetNames[x]);
	        	}
        }
   
        //Add Library Columns
        if(allLibraryNames != null) {
	        	for(int x=0; x<allLibraryNames.length; x++)
	        		mapper.addIntField(LIBRARY_COUNT_ALL + x, "#" + allLibraryNames[x], "contig", 
	        				"L__" + allLibraryNames[x], GROUP_NAME_LIB, GROUP_DESC_LIB, 
	        				"Library " + allLibraryNames[x]);
	        	for(int x=0; x<allLibraryNames.length; x++)
	        		mapper.addFloatField(N_LIBRARY_COUNT_ALL + x, allLibraryNames[x], "contig", 
	        				"LN__" + allLibraryNames[x], GROUP_NAME_LIB, GROUP_DESC_LIB, 
	        				allLibraryTitles[x]);      	
        }
        if(pLabels != null) {
	        	for(int x=0; x<pLabels.length; x++) {
	        		mapper.addFloatField(P_VALUES + x, pLabels[x], "contig", 
	        				"P_" + pLabels[x], GROUP_NAME_PVAL, GROUP_DESC_PVAL, 
	        				pTitles[x]);
	        	}
        }
       	
        mapper.addFloatField( RSTAT_FIELD, "Rstat", "contig", "rstat", 
        		GROUP_NAME_RSTAT, GROUP_DESC_RSTAT, 
        		"All libraries for the sequence." );
        mapper.addFloatField( RSTAT_INC_FIELD, "Rstat (Include)", null , null, 
        		GROUP_NAME_RSTAT, GROUP_DESC_RSTAT, 
        		"Included libraries for the sequence (Filtered only)." );

        // Counts for UniProt and Nucleotide hits
        
        mapper.addStringField( CNT_TAXO, "#Taxonomy", "contig", 
        		"cnt_taxo", GROUP_NAME_CNTS, GROUP_DESC_CNTS, 
        		"Number of different taxomony hits for contig." ); 
        
        mapper.addStringField( CNT_SPECIES, "#Species", "contig", 
        		"cnt_species", GROUP_NAME_CNTS, GROUP_DESC_CNTS, 
        		"Number of different species aligned to the sequence." ); 
        
        mapper.addStringField( CNT_GENE, "#Genes Rep", "contig", 
        		"cnt_gene", GROUP_NAME_CNTS, GROUP_DESC_CNTS, 
        		"Number of different unique descriptions of hit alignments." ); 
        
        mapper.addStringField( CNT_OVERLAP, "#Minimal overlap", "contig", 
        		"cnt_overlap", GROUP_NAME_CNTS, GROUP_DESC_CNTS, 
        		"Number of hits that have coordiantes outside of the BestHit." );  
        
        mapper.addStringField( CNT_SWISS, "#SwissProt", "contig", 
        		"cnt_swiss", GROUP_NAME_CNTS, GROUP_DESC_CNTS, 
        		"Total hits from Swissprot." );  
        
        mapper.addStringField( CNT_TREMBL, "#TrEMBL", "contig", 
        		"cnt_trembl", GROUP_NAME_CNTS, GROUP_DESC_CNTS, 
        		"Total hits from Trembl." );
        // CAS 2/6/15 added ncbi
        mapper.addStringField( CNT_NCBI, "#NCBI", "contig", 
        		"cnt_gi", GROUP_NAME_CNTS, GROUP_DESC_CNTS, 
        		"Total hits from NCBI nr." );
        
        mapper.addStringField( CNT_NT, "#Nucleotide", "contig", 
        		"cnt_nt", GROUP_NAME_CNTS, GROUP_DESC_CNTS, 
        		"Number of hits from other databases (generally Nucleotide)." ); 
        
        // First Best match
        mapper.addStringField( FIRST_BEST_UNIPROT_FIELD, "Best Eval (EV)", TABLE_FIRST_BEST, 
        		"uniprot_id", GROUP_NAME_FIRST_BEST, GROUP_DESC_FIRST_BEST, 
        		"The annoDB ID with best eval to the sequence." ); 
        mapper.setFieldSubQuery(FIRST_BEST_UNIPROT_FIELD, "firstbestid", TABLE_FIRST_BEST + ".uniprot_id");
        
        mapper.addStringField( FIRST_BEST_DESCRIPTION, "EV Description", TABLE_FIRST_BEST_DETAIL, 
        		"description", GROUP_NAME_FIRST_BEST, GROUP_DESC_FIRST_BEST, 
        		"The description of the BestEval." ); 
        mapper.setFieldSubQuery(FIRST_BEST_DESCRIPTION, "firstbestdescrip", TABLE_FIRST_BEST_DETAIL + ".description");
         
        mapper.addStringField( FIRST_BEST_SPECIES, "EV Species", TABLE_FIRST_BEST_DETAIL, 
        		"species", GROUP_NAME_FIRST_BEST, GROUP_DESC_FIRST_BEST, 
        		"The species of the BestEval." ); 
        mapper.setFieldSubQuery(FIRST_BEST_SPECIES, "firstbestspecies", TABLE_FIRST_BEST_DETAIL + ".species");
        
        mapper.addStringField( FIRST_BEST_DBTYPE_FIELD, "EV DB type", TABLE_FIRST_BEST, 
        		"dbtype", GROUP_NAME_FIRST_BEST, GROUP_DESC_FIRST_BEST, 
        		"The type (e.g. SP (SwissProt) or TR (TrEMBL)) of the BestEval." ); 
        mapper.setFieldSubQuery(FIRST_BEST_DBTYPE_FIELD, "firstbestdbtype", TABLE_FIRST_BEST + ".dbtype");
        
        mapper.addStringField( FIRST_BEST_TAXO_FIELD, "EV Taxo", TABLE_FIRST_BEST, 
        		"taxonomy", GROUP_NAME_FIRST_BEST, GROUP_DESC_FIRST_BEST, 
        		"Taxonomy (or sequence type) of the database for the BestEval." ); 
        mapper.setFieldSubQuery(FIRST_BEST_TAXO_FIELD, "firstbesttaxo", TABLE_FIRST_BEST + ".taxonomy");
       
        mapper.addFloatField( FIRST_BEST_EVALUE_FIELD, "EV Eval", TABLE_FIRST_BEST, 
        		"e_value", GROUP_NAME_FIRST_BEST, GROUP_DESC_FIRST_BEST, 
        		"The E-value of the BestEval." );
        mapper.setFieldSubQuery(FIRST_BEST_EVALUE_FIELD, "firstbesteval", TABLE_FIRST_BEST + ".e_value");
        
        mapper.addIntField( FIRST_BEST_BIT_SCORE_FIELD, "EV Bit Score", TABLE_FIRST_BEST, 
        		"bit_score", GROUP_NAME_FIRST_BEST, GROUP_DESC_FIRST_BEST, 
        		"The bit score of the BestEval." );
        mapper.setFieldSubQuery(FIRST_BEST_BIT_SCORE_FIELD, "firstbestbitscore", TABLE_FIRST_BEST + ".bit_score");
        
        mapper.addIntField( FIRST_BEST_PERCENT_IDENT, "EV % Identity", TABLE_FIRST_BEST,
        		"percent_id", GROUP_NAME_FIRST_BEST, GROUP_DESC_FIRST_BEST,
        		"The percent identity of the BestEval");
        mapper.setFieldSubQuery(FIRST_BEST_PERCENT_IDENT, "firstbestpercentid", TABLE_FIRST_BEST + ".percent_id");
 
        mapper.addIntField( FIRST_BEST_ALIGN_LEN_FIELD, "EV Align Len", TABLE_FIRST_BEST, 
        		"alignment_len", GROUP_NAME_FIRST_BEST, GROUP_DESC_FIRST_BEST, 
        		"The alignment length of the BestEval." ); 
        mapper.setFieldSubQuery(FIRST_BEST_ALIGN_LEN_FIELD, "firstbestalignlen", TABLE_FIRST_BEST + ".alignment_len");
        
        mapper.addIntField( FIRST_BEST_CTG_START_FIELD, "EV Seq Start", TABLE_FIRST_BEST, 
        		"ctg_start", GROUP_NAME_FIRST_BEST, GROUP_DESC_FIRST_BEST, 
        		"Start of the match of the sequence for the BestEval." );
        mapper.setFieldSubQuery(FIRST_BEST_CTG_START_FIELD, "firstbestctgstart", TABLE_FIRST_BEST + ".ctg_start");
        
        mapper.addIntField( FIRST_BEST_CTG_END_FIELD, "EV Seq End", TABLE_FIRST_BEST, 
        		"ctg_end", GROUP_NAME_FIRST_BEST, GROUP_DESC_FIRST_BEST, 
        		"End of the match of the sequence for the BestEval." );
        mapper.setFieldSubQuery(FIRST_BEST_CTG_END_FIELD, "firstbestctgend", TABLE_FIRST_BEST + ".ctg_end");
        
        mapper.addIntField( FIRST_BEST_PRO_START_FIELD, "EV Hit Start", TABLE_FIRST_BEST, 
        		"prot_start", GROUP_NAME_FIRST_BEST, GROUP_DESC_FIRST_BEST, 
        		"Start of match of the HSP for the BestEval." );
        mapper.setFieldSubQuery(FIRST_BEST_PRO_START_FIELD, "firstbestprotstart", TABLE_FIRST_BEST + ".prot_start");
        
        mapper.addIntField( FIRST_BEST_PRO_END_FIELD, "EV Hit End", TABLE_FIRST_BEST, 
        		"prot_end", GROUP_NAME_FIRST_BEST, GROUP_DESC_FIRST_BEST, 
        		"End of match of the HSP for the BestEval." );
        mapper.setFieldSubQuery(FIRST_BEST_PRO_END_FIELD, "firstbestprotend", TABLE_FIRST_BEST + ".prot_end");
        
        if(qTab.getParentFrame().hasKEGG())
	        	mapper.addStringField( FIRST_BEST_KEGG, "EV Hit KEGG", TABLE_FIRST_BEST_DETAIL, 
	        		"kegg", GROUP_NAME_FIRST_BEST, GROUP_DESC_FIRST_BEST, 
	        		"KEGG ID for the overall BestEval." );

        if(qTab.getParentFrame().hasPFAM())
	        	mapper.addStringField( FIRST_BEST_PFAM, "EV Hit PFam", TABLE_FIRST_BEST_DETAIL, 
	        		"pfam", GROUP_NAME_FIRST_BEST, GROUP_DESC_FIRST_BEST, 
	        		"PFam ID for the overall BestEval." );

        if(qTab.getParentFrame().hasEC())
	        	mapper.addStringField( FIRST_BEST_EC, "EV Hit EC", TABLE_FIRST_BEST_DETAIL, 
	        		"ec", GROUP_NAME_FIRST_BEST, GROUP_DESC_FIRST_BEST, 
	        		"EC ID for the overall BestEval." );

        // Overall Best match
        mapper.addStringField( OVER_BEST_UNIPROT_FIELD, "BestAnno (AN)", TABLE_OVER_BEST, 
        		"uniprot_id", GROUP_NAME_OVER_BEST, GROUP_DESC_OVER_BEST, 
        		"The annoDB Id with the overall best HSP to the sequence." ); 
        mapper.setFieldSubQuery(OVER_BEST_UNIPROT_FIELD, "overbestid", TABLE_OVER_BEST + ".uniprot_id");
       
        mapper.addStringField( OVER_BEST_DESCRIPTION, "AN Description", TABLE_OVER_BEST_DETAIL, 
        		"description", GROUP_NAME_OVER_BEST, GROUP_DESC_OVER_BEST, 
        		"The description of the overall BestHit." ); 
         
        mapper.addStringField( OVER_BEST_SPECIES, "AN Species", TABLE_OVER_BEST_DETAIL, 
        		"species", GROUP_NAME_OVER_BEST, GROUP_DESC_OVER_BEST, 
        		"The species of the overall BestAnno." ); 
        
        mapper.addStringField( OVER_BEST_DBTYPE_FIELD, "AN DB type", TABLE_OVER_BEST, 
        		"dbtype", GROUP_NAME_OVER_BEST, GROUP_DESC_OVER_BEST, 
        		"The type (e.g. SP (SwissProt) or TR (TrEMBL)) of the overall BestAnno." ); 
        
        mapper.addStringField( OVER_BEST_TAXO_FIELD, "AN Taxo", TABLE_OVER_BEST, 
        		"taxonomy", GROUP_NAME_OVER_BEST, GROUP_DESC_OVER_BEST, 
        		"Taxonomy (or sequence type) of the database for the overall BestAnno." ); 
       
        mapper.addFloatField( OVER_BEST_EVALUE_FIELD, "AN Eval", TABLE_OVER_BEST, 
        		"e_value", GROUP_NAME_OVER_BEST, GROUP_DESC_OVER_BEST, 
        		"The E-value of the overall BestAnno." );
        
        mapper.addIntField( OVER_BEST_BIT_SCORE_FIELD, "AN Bit Score", TABLE_OVER_BEST, 
        		"bit_score", GROUP_NAME_OVER_BEST, GROUP_DESC_OVER_BEST, 
        		"The bit score of the overall BestAnno." );
        
        mapper.addIntField( OVER_BEST_PERCENT_IDENT, "AN % Identity", TABLE_OVER_BEST,
        		"percent_id", GROUP_NAME_OVER_BEST, GROUP_DESC_OVER_BEST,
        		"The percent identity of the overall BestAnno");
 
        mapper.addIntField( OVER_BEST_ALIGN_LEN_FIELD, "AN Align Len", TABLE_OVER_BEST, 
        		"alignment_len", GROUP_NAME_OVER_BEST, GROUP_DESC_OVER_BEST, 
        		"The alignment length of the overall best HSP of the overall BestAnno." ); 
        
        mapper.addIntField( OVER_BEST_CTG_START_FIELD, "AN Seq Start", TABLE_OVER_BEST, 
        		"ctg_start", GROUP_NAME_OVER_BEST, GROUP_DESC_OVER_BEST, 
        		"Start of the match to the sequence for the overall BestAnno." );
        
        mapper.addIntField( OVER_BEST_CTG_END_FIELD, "AN Seq End", TABLE_OVER_BEST, 
        		"ctg_end", GROUP_NAME_OVER_BEST, GROUP_DESC_OVER_BEST, 
        		"End of the match to the sequence for the overall BestAnno." );
        
        mapper.addIntField( OVER_BEST_PRO_START_FIELD, "AN Hit Start", TABLE_OVER_BEST, 
        		"prot_start", GROUP_NAME_OVER_BEST, GROUP_DESC_OVER_BEST, 
        		"Start of match to the HSP for the overall BestAnno." );
        
        mapper.addIntField( OVER_BEST_PRO_END_FIELD, "AN Hit End", TABLE_OVER_BEST, 
        		"prot_end", GROUP_NAME_OVER_BEST, GROUP_DESC_OVER_BEST, 
        		"End of match of the HSP for the overall BestAnno." );

        if(qTab.getParentFrame().hasKEGG())
	        	mapper.addStringField( OVER_BEST_KEGG, "AN KEGG", TABLE_OVER_BEST_DETAIL, 
	        		"kegg", GROUP_NAME_OVER_BEST, GROUP_DESC_OVER_BEST, 
	        		"KEGG ID for the overall BestAnno." );

        if(qTab.getParentFrame().hasPFAM())
	        	mapper.addStringField( OVER_BEST_PFAM, "AN PFam", TABLE_OVER_BEST_DETAIL, 
	        		"pfam", GROUP_NAME_OVER_BEST, GROUP_DESC_OVER_BEST, 
	        		"PFam ID for the overall BestAnno." );

        if(qTab.getParentFrame().hasEC())
	        	mapper.addStringField( OVER_BEST_EC, "AN EC", TABLE_OVER_BEST_DETAIL, 
	        		"ec", GROUP_NAME_OVER_BEST, GROUP_DESC_OVER_BEST, 
	        		"EC ID for the overall BestAnno." );
// SNP
        if(parentFrame.hasAssembly()) {
        		mapper.addIntField( SNP_COUNT_FIELD, "SNP Count", "contig", "snp_count", 
            		GROUP_NAME_SNPORF, GROUP_DESC_SNPORF, 
            		"The number of SNPs detected in the contig." );
        		mapper.addIntField( SNP_INDEL_FIELD, "SNP InDel", "contig", "indel_count", 
              		GROUP_NAME_SNPORF, GROUP_DESC_SNPORF, 
              		"The number of SNP insertions/deletions." );        	
        }
        // Open Reading Frames
        if(!parentFrame.isProteinDB()) {
	        mapper.addIntField( ORF_CODING_FRAME, "ORF Frame", "contig", 
	        		"o_frame", GROUP_NAME_SNPORF, GROUP_DESC_SNPORF, 
	        		"Frame position of the best ORF." );
	 
	        String ORFlen = "(o_coding_end - o_coding_start + 1)"; 
	        mapper.addIntField( ORF_CODING_LENGTH, "ORF Len", null, 
	        		null, GROUP_NAME_SNPORF, GROUP_DESC_SNPORF, 
	        		"Length of the best ORF in bases." );
	        mapper.setFieldSubQuery(ORF_CODING_LENGTH, "o_coding_length", ORFlen);
	     
	        mapper.addIntField( ORF_START, "ORF Start", "contig", 
	        		"o_coding_start", GROUP_NAME_SNPORF, GROUP_DESC_SNPORF, 
	        		"ORF start (may not have start codon, see Has Start)." ); 
	        
	        mapper.addIntField( ORF_END, "ORF End", "contig", 
	        		"o_coding_end",  GROUP_NAME_SNPORF, GROUP_DESC_SNPORF, 
	        		"ORF end (may not have stop codon, see Has Stop)." );
	        
	        mapper.addBoolField( ORF_HAS_START, "Has Start", "contig", 
	        		"o_coding_has_begin", GROUP_NAME_SNPORF, GROUP_DESC_SNPORF, 
	        		"ORF has start codon." );
	        
	        mapper.addBoolField( ORF_HAS_END, "Has Stop", "contig", 
	        		"o_coding_has_end", GROUP_NAME_SNPORF, GROUP_DESC_SNPORF, 
	        		"ORF has stop codon." );
	        
	        mapper.addBoolField( USED_PROTEIN_FRAME, "Used Protein", "contig", 
	        		"p_coding_has_begin", GROUP_NAME_SNPORF, GROUP_DESC_SNPORF, 
	        		"Protein frame was used." );   
        }
        
        if(parentFrame != null && parentFrame.getFieldTab() != null)
        		parentFrame.getFieldTab().addNFoldFields(mapper);
      
        // SET DEFAULT COLUMNS
        mapper.setDefaultFieldIDs ( new int [] { /*RECORD_NUM_FIELD,*/
        											CONTIG_ID_FIELD, 
        											CONSENSUS_BASES_FIELD,
        											FIRST_BEST_DESCRIPTION, 
        											FIRST_BEST_EVALUE_FIELD
        											} );
        return mapper;
    }
 
    public boolean isAllContigs ( ) 
    { 
    		return getAllPassingPredicate ().equals( ALL_CONTIGS_PRED )
    			&& !hasAnnotation() && !hasNoAnnotation() && !isLibrarySelected(); 
    }

    public String getContigListSQL ( FieldMapper fields, FieldTab fTab, String [] contigIDs, String strAssemblyIDs )
    {
 
	    	String strQuery = "";
	    	String strRStat = "";
	    	
	    	String [] libs = getAllRequiredLibs(fTab);
	    	if(libs != null && libs.length > 0) {
	    		for(int x=0; x<libs.length; x++) {
	    			strRStat += ", L__" + libs[x] + " AS LIB" + (x+1);
	    			strRStat += ", LN__" + libs[x] + " AS LIBN" + (x+1);
	    		}
	    	}
    	
   		strQuery = "SELECT " + fields.getDBFieldList() + strRStat + " FROM contig ";
  
		if ( fields.haveDBFieldWithTable(TABLE_FIRST_BEST) || fields.haveDBFieldWithTable(TABLE_FIRST_BEST_DETAIL) )	
			strQuery += " LEFT OUTER JOIN pja_db_unitrans_hits AS " + TABLE_FIRST_BEST + " ON " +
					"contig.PID = " + TABLE_FIRST_BEST + ".PID ";
		if ( fields.haveDBFieldWithTable(TABLE_OVER_BEST) || fields.haveDBFieldWithTable(TABLE_OVER_BEST_DETAIL) )	
			strQuery += " LEFT OUTER JOIN pja_db_unitrans_hits AS " + TABLE_OVER_BEST + " ON " +
					"contig.PIDov = " + TABLE_OVER_BEST + ".PID ";

		if( fields.haveDBFieldWithTable(TABLE_FIRST_BEST_DETAIL) )
			strQuery += " LEFT OUTER JOIN pja_db_unique_hits AS " + TABLE_FIRST_BEST_DETAIL + " ON " +
					TABLE_FIRST_BEST + ".DUHID = " + TABLE_FIRST_BEST_DETAIL + ".DUHID ";
		if( fields.haveDBFieldWithTable(TABLE_OVER_BEST_DETAIL) )
			strQuery += " LEFT OUTER JOIN pja_db_unique_hits AS " + TABLE_OVER_BEST_DETAIL + " ON " +
					TABLE_OVER_BEST + ".DUHID = " + TABLE_OVER_BEST_DETAIL + ".DUHID ";
		
		String contigList = "('" + contigIDs[0] + "'";
		for(int x=1; x<contigIDs.length; x++)
			contigList += ", '" + contigIDs[x] + "'";
		contigList += ")";
		
		strQuery +=	" WHERE contig.assemblyid IN " 
				+ strAssemblyIDs + " AND contig.contigid IN " + contigList  + " ORDER BY contig.contigid";

		return strQuery;
    }

    /**
     * Builds the query string based on the current type and fields 
     * called from BasicQueryData/QueryData.loadQueryResults
     */
    public String getContigListSQL ( FieldMapper fields, FieldTab fTab, String strAssemblyIDs )
    {
	    	if (debug) System.err.println("getContigListQuery");
	    	String strQuery = "";
	    	String strRStat = "";
	    	
	    	String [] libs = getAllRequiredLibs(fTab);
	
	    	if(libs != null && libs.length > 0) {    		
	    		for(int x=0; x<libs.length; x++) {
	    			strRStat += ", L__" + libs[x] + " AS LIB" + (x+1);
	    			strRStat += ", LN__" + libs[x] + " AS LIBN" + (x+1);
	    		}
	    	}
    	
   		strQuery = "SELECT " + fields.getDBFieldList() + strRStat + " FROM contig ";
  
		if ( fields.haveDBFieldWithTable(TABLE_FIRST_BEST) || fields.haveDBFieldWithTable(TABLE_FIRST_BEST_DETAIL) )	
			strQuery += " LEFT OUTER JOIN pja_db_unitrans_hits AS " + TABLE_FIRST_BEST + " ON " +
					"contig.PID = " + TABLE_FIRST_BEST + ".PID ";
		if ( fields.haveDBFieldWithTable(TABLE_OVER_BEST) || fields.haveDBFieldWithTable(TABLE_OVER_BEST_DETAIL) )	
			strQuery += " LEFT OUTER JOIN pja_db_unitrans_hits AS " + TABLE_OVER_BEST + " ON " +
					"contig.PIDov = " + TABLE_OVER_BEST + ".PID ";

		if( fields.haveDBFieldWithTable(TABLE_FIRST_BEST_DETAIL) )
			strQuery += " LEFT OUTER JOIN pja_db_unique_hits AS " + TABLE_FIRST_BEST_DETAIL + " ON " +
					TABLE_FIRST_BEST + ".DUHID = " + TABLE_FIRST_BEST_DETAIL + ".DUHID ";
		if( fields.haveDBFieldWithTable(TABLE_OVER_BEST_DETAIL) )
			strQuery += " LEFT OUTER JOIN pja_db_unique_hits AS " + TABLE_OVER_BEST_DETAIL + " ON " +
					TABLE_OVER_BEST + ".DUHID = " + TABLE_OVER_BEST_DETAIL + ".DUHID ";

		String noAnno = "";
		if(hasNoAnnotation()) {
			noAnno = "contig.bestmatchid IS NULL AND ";
		}
		
		if (hasAnnotation()) // must go at end of query string
			strQuery += " WHERE " + noAnno + "contig.bestmatchid IS NOT NULL AND contig.assemblyid IN " 
				+ strAssemblyIDs + " ORDER BY contig.bestmatchid";
		else
			strQuery +=	" WHERE " + noAnno + "contig.assemblyid IN " 
				+ strAssemblyIDs + " ORDER BY contig.contigid";

		return strQuery;
    }
    
    /**
     * Builds the query string based on the current type and fields 
     * called from BasicQueryData.loadQueryResults
     */
    public String getHitIDListSQL ( FieldMapper fields, String strAssemblyIDs )
    {
	    	String strQuery = "";
	    	strQuery = "SELECT " + fields.getDBFieldList() + " FROM contig ";
  
		if ( fields.haveDBFieldWithTable(TABLE_FIRST_BEST) || fields.haveDBFieldWithTable(TABLE_FIRST_BEST_DETAIL) )	
			strQuery += " LEFT OUTER JOIN pja_db_unitrans_hits AS " + TABLE_FIRST_BEST + " ON " +
					"contig.PID = " + TABLE_FIRST_BEST + ".PID ";
		if ( fields.haveDBFieldWithTable(TABLE_OVER_BEST) || fields.haveDBFieldWithTable(TABLE_OVER_BEST_DETAIL) )	
			strQuery += " LEFT OUTER JOIN pja_db_unitrans_hits AS " + TABLE_OVER_BEST + " ON " +
					"contig.PIDov = " + TABLE_OVER_BEST + ".PID ";
		if( fields.haveDBFieldWithTable(TABLE_FIRST_BEST_DETAIL) )
			strQuery += " LEFT OUTER JOIN pja_db_unique_hits AS " + TABLE_FIRST_BEST_DETAIL + " ON " +
					TABLE_FIRST_BEST + ".DUHID = " + TABLE_FIRST_BEST_DETAIL + ".DUHID ";
		if( fields.haveDBFieldWithTable(TABLE_OVER_BEST_DETAIL) )
			strQuery += " LEFT OUTER JOIN pja_db_unique_hits AS " + TABLE_OVER_BEST_DETAIL + " ON " +
					TABLE_OVER_BEST + ".DUHID = " + TABLE_OVER_BEST_DETAIL + ".DUHID ";

		String noAnno = "";
		if(hasNoAnnotation()) {
			noAnno = "contig.bestmatchid IS NULL AND ";
		}

		if (hasAnnotation()) // must go at end of query string
			strQuery += " WHERE " + noAnno + "contig.bestmatchid!='NULL' AND contig.assemblyid IN " 
				+ strAssemblyIDs + " ORDER BY contig.bestmatchid";
		else
			strQuery +=	" WHERE " + noAnno + "contig.assemblyid IN " 
				+ strAssemblyIDs + " ORDER BY contig.contigid";

		return strQuery;
    }
    
    /**
     * get the list of contigs to include in the query
     * called from QueryData.loadQueryResults
     */
	public PrefixTree getIncludeFilterList ( SessionData theSession ) throws Exception
	{
		PrefixTree out = new PrefixTree ();
		if ( loadFilterList ( theSession, getIncludePredicate (), out, null ) )
			return out;
		else
			return null;
	}	
	
    /**
     * get the list of contigs to exclude in the query
     * called from QueryData.loadQueryResults
     */
	public PrefixTree getExcludeFilterList ( SessionData theSession ) throws Exception
	{
		PrefixTree out = new PrefixTree ();
		if ( loadFilterList ( theSession, getExcludePredicate (), out, null ) )
			return out;
		else
			return null;
	}
	
	// called from getExcludedFilterList and getIncludedFilterList
	private boolean loadFilterList ( 	SessionData theSession, 
										String strPred,								
										PrefixTree outTree,
										Vector<String> outVector ) 
	throws Exception
	{
		Connection conn = null;
		Statement stmt = null;

		if (StringHelpers.isEmpty(strPred))
			return false; // Null query

		// Build up the query
		String strQ = "SELECT DISTINCT contig.contigid ";
		if (!StringHelpers.isEmpty(strPred) && strPred.indexOf("pja_db_unitrans_hits.") >= 0)
			strQ += "FROM contig JOIN pja_db_unitrans_hits ON contig.contigid = pja_db_unitrans_hits.contigid"; 	
		else
			strQ += "FROM contig";
		strQ += " JOIN contclone ON contig.contigid = contclone.contigid"; 
		if(bGOID && strGOID.length() > 0)
			strQ += " JOIN pja_unitrans_go ON contig.CTGID = pja_unitrans_go.CTGID AND pja_unitrans_go.gonum = " + strGOID;
		strQ += " WHERE contig.assemblyid IN "
				+ theSession.getAssemblyIDList(false);
		if (!StringHelpers.isEmpty(strPred) && strPred.indexOf("pja_db_unitrans_hits.") >= 0) strQ += " AND pja_db_unitrans_hits.CTGID=contig.CTGID";
		if(!StringHelpers.isEmpty(strPred)) strQ += " AND " + strPred;

		// Load the filter list of contigs
		try {
			conn = theSession.getConnection();
			
			stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
						ResultSet.CONCUR_READ_ONLY);
			if (debug) System.err.println("loadFilterList: " + strQ);
			
			ResultSet rset = stmt.executeQuery(strQ);

			while (rset.next()) {
				String strContig = rset.getString(1);
				if (outTree != null) {
					outTree.put(strContig, strContig);
				}
				if (outVector != null) {
					outVector.add(strContig);
				}
			}

			return true;
		} finally {
			if (stmt != null) stmt.close();
			if (conn != null) conn.close();
		}
	}
	
	// for CachedTable
	private String getAllPassingPredicate ( )
	{	
		String incPred = getIncludePredicate();
		String exPred = getExcludePredicate();
		if ( incPred == null && exPred == null)
			return ALL_CONTIGS_PRED; // All contigs
		
		if ( getExcludePredicate () != null )
			return appendANDPredicate ( incPred, 
						"( " + exPred + " ) = false"  );
		else
			return incPred;
	}
	
	/****************************************************
	 * example strings:
	 * input: incMode = greatest, exMode = least, greaterThan=false
	 *     10 * (contig.LN__Wb) <= (contig.LN__WbL) and (contig.LN__Wb) > 0
	 * input: incMode = least, exMode = greatest, greaterThan=false
	 *     (contig.LN__Wb) >= 10 * (contig.LN__WbL) and (contig.LN__WbL) > 0
	 */
	private String getNFoldSQL(String incMode, String mode, String exMode, 
			String [] selectedIncLibs, String [] selectedExLibs, boolean greaterThan) {

		String exPred = "";

		// first clause
	    if(selectedIncLibs.length == 1) incMode = ""; // sql predicate 
		if(!greaterThan)
			exPred += dNFoldLibCount + " * "; 	
		exPred += incMode + "(" + "contig.L" + mode + "__" + selectedIncLibs[0];
		
		for(int x=1; x<selectedIncLibs.length; x++) {
			exPred += ", contig.L" + mode + "__" + selectedIncLibs[x];
		}
		
		// >= or <=
	    String compare = greaterThan?" >= ":" <= ";
		exPred += ")" + compare;
		
		// second clause
		if(selectedExLibs.length == 1) exMode = "";
		if(greaterThan)
			exPred += dNFoldLibCount + " * "; 
		exPred += exMode + "(" + "contig.L" + mode + "__" + selectedExLibs[0];
		for(int x=1; x<selectedExLibs.length; x++) {
			exPred += ", contig.L" + mode + "__" + selectedExLibs[x];
		}
		
		// third clause
		if (!greaterThan) {
		    exPred += ") and " + incMode + "(" + "contig.L" + mode + "__" + selectedIncLibs[0];
        		for(int x=1; x<selectedIncLibs.length; x++) {
        			exPred += ", contig.L" + mode + "__" + selectedIncLibs[x];
        		}
		}
		else {
		    exPred += ") and " + exMode + "(" + "contig.L" + mode + "__" + selectedExLibs[0];
		    for(int x=1; x<selectedExLibs.length; x++) {
                exPred += ", contig.L" + mode + "__" + selectedExLibs[x];
            }
		}
		exPred += ") > 0";
		
		return exPred;
	}
	
	private String getIncludePredicate ( )
	{	
		String strSQL = null;	
		if ( nFilterHasNotes == FilterContigData.FILTER_INCLUDE )
			strSQL = appendANDPredicate ( strSQL, "(contig.notes IS NOT NULL AND contig.notes != \"\")" );
		if ( nFilterHasNs == FilterContigData.FILTER_INCLUDE )
			strSQL = appendANDPredicate ( strSQL, "contig.has_ns = TRUE" );
		
		if ( bCtgNumAligns ) {
			String boolOp;
			if(bCtgNumAlignsLT)
				boolOp = " <= ";
			else
				boolOp = " >= ";
			strSQL = appendANDPredicate ( strSQL, "contig.numclones" + boolOp + nCtgNumAligns );
		}
		
		if ( bCtgLength ) {
			String boolOp;
			if(bCtgLengthLT)
				boolOp = " <= ";
			else
				boolOp = " >= ";
			strSQL = appendANDPredicate ( strSQL, "contig.consensus_bases" + boolOp + nCtgLength );
		}
		
		if ( bCtgTotalExpLevel ) {
			String boolOp;
			if(bCtgTotalExpLevelLT)
				boolOp = " <= ";
			else
				boolOp = " >= ";
			strSQL = appendANDPredicate ( strSQL, "contig.totalexp" + boolOp + nCtgTotalExpLevel );
		}
		
		if ( bGtrEquSNPs )
			strSQL = appendANDPredicate ( strSQL, "contig.snp_count >= " + nGtrEquSNPs );
		if ( bLessEquSNPs )
			strSQL = appendANDPredicate ( strSQL, "contig.snp_count <= " + nLessEquSNPs );	
		
		if( bNumIncLibrary && selectedIncLibs.length > 0) {
			String libPred = "";
			String mode = bNormalizedMode?"N":"";

			libPred = "contig.L" + mode + "__" + selectedIncLibs[0] + " >= " + dNumIncLibs;
			for(int x=1; x<selectedIncLibs.length; x++)
				libPred = appendPredicate( libPred, (bNumIncLibsAnd?1:0), "contig.L" + mode + "__" + selectedIncLibs[x] + " >= " + dNumIncLibs);

			strSQL = appendANDPredicate(strSQL, libPred);
		}
		
		if( bNumExLibrary && selectedExLibs.length > 0 ) {
			String libPred = "";
			String mode = bNormalizedMode?"N":"";

			libPred = "contig.L" + mode + "__" + selectedExLibs[0] + " <= " + dNumExLibs;
			for(int x=1; x<selectedExLibs.length; x++)
				libPred = appendPredicate( libPred, (bNumExLibsAnd?1:0), "contig.L" + mode + "__" + selectedExLibs[x] + " <= " + dNumExLibs);

			strSQL = appendANDPredicate(strSQL, libPred);
		}

		if( bNFoldLibrary && selectedExLibs.length > 0 && selectedIncLibs.length > 0) {
			String mode = bNormalizedMode?"N":"";
			
			if(nFoldRange == 0)
				strSQL = appendANDPredicate(strSQL, 
						getNFoldSQL("least", mode, "greatest", selectedIncLibs, selectedExLibs, true));
			else if(nFoldRange == 1)
				strSQL = appendANDPredicate(strSQL, 
						getNFoldSQL("greatest", mode, "least", selectedIncLibs, selectedExLibs, false));
			else {
				String combined = appendORPredicate(
						getNFoldSQL("least", mode, "greatest", selectedIncLibs, selectedExLibs, true), 
						getNFoldSQL("greatest", mode, "least", selectedIncLibs, selectedExLibs, false));
				strSQL = appendANDPredicate(strSQL, combined);
			}
		}
		
		// Good UTR tests
		String strORF="";
		if (bORFCoding) 
			strORF = "contig.o_frame IS NOT NULL " +
							" AND o_coding_end - o_coding_start >= " + nORFMinNT;
		if (bProteinORF)
			strORF = appendANDPredicate ( strORF,
					"p_coding_has_begin=TRUE"); // the field is mis-named
		if ( bBothUTRs )
			strORF = appendANDPredicate ( strORF, 
					" o_coding_has_begin = TRUE AND o_coding_has_end = TRUE " );	
		if (!strORF.equals(""))
			strSQL = appendANDPredicate ( strSQL, strORF );
	
				
  		String strUniProt = null;
  		
  		if(bHasAnnotation) {
  			String fieldType = bFirstBest?"ov":"";

  			if ( bDBHitLen ) 
  			{
  				String strQ = "(contig.PID" + fieldType + " = pja_db_unitrans_hits.PID AND " +
								"pja_db_unitrans_hits.alignment_len";
  				strQ += (bDBHitLenLT? " <= ":" >= ");
  				strQ += + nDBHitLen + ")";
  				strUniProt = appendPredicate ( strUniProt, nDBHitAndOr, strQ );
  			}
  			if ( bDBHitEval )
  			{
  				String strQ = 	"contig.PID" + fieldType +" = pja_db_unitrans_hits.PID AND " +
  								"pja_db_unitrans_hits.e_value";
  				strQ += (bDBHitEvalLT?" <= ":" >= ");
  				strQ += dDBHitEval;
  				strUniProt = appendPredicate ( strUniProt, nDBHitAndOr, strQ );		
  			}
  			if ( bDBHitIdent )
  			{
  				String strQ = 	"contig.PID" + fieldType + " = pja_db_unitrans_hits.PID AND " +
  								"pja_db_unitrans_hits.percent_id";
  				strQ += (bDBHitIdentLT?" <= ":" >= ");
  				strQ += nDBHitIdent;
  				strUniProt = appendPredicate ( strUniProt, nDBHitAndOr, strQ );		
  			}
  			if ( bDBHitBitScore )
  			{
  				String strQ = 	"contig.PID" + fieldType + " = pja_db_unitrans_hits.PID AND " +
  								"pja_db_unitrans_hits.bit_score";
  				strQ += (bDBHitBitScoreLT?" <= ":" >= ");
  				strQ += nDBHitBitScore;
  				strUniProt = appendPredicate ( strUniProt, nDBHitAndOr, strQ );		
  			}
  			//XXX
  			strSQL = appendANDPredicate ( strSQL, strUniProt );	
  		}
  		
		// Include contigs
		if ( includeContigIDs != null && includeContigIDs.size() > 0 )
		{
			strSQL = appendANDPredicate ( strSQL, "contig.contigid IN ( '" + 
				StringHelpers.join( includeContigIDs.iterator(), "', '" )  
												+ "' ) " );
		}
		
		// Include contigs with clones
		if ( includeCloneIDs != null && includeCloneIDs.size() > 0 )
		{
			strSQL = appendANDPredicate ( strSQL, "contclone.cloneid IN ( '" + 
					StringHelpers.join( includeCloneIDs.iterator(), "', '" )  
												+ "' ) " );
		}
		
		// Include contigs with specific uniprot hits
		if ( includeUniProtIDs != null && includeUniProtIDs.size() > 0 )
		{
			strSQL = appendANDPredicate ( strSQL, "contig.bestmatchid IN ( '" + 
					StringHelpers.join( includeUniProtIDs.iterator(), "', '" )  
												+ "' ) " );
		}
		
		if( bPValFilter && pValCols != null && pValCols.length > 0) {
			String boolVal = "";
			if(bPValBoolAnd)
				boolVal = " AND ";
			else
				boolVal = " OR ";
			
			String pValQuery = "(abs(contig.P_" + pValCols[0] + ") < " + dPValLimit + ")";
			for(int x=1; x<pValCols.length; x++) {
				pValQuery += boolVal + "(abs(contig.P_" + pValCols[x] + ") < " + dPValLimit + ")";
			}			
			strSQL = appendANDPredicate(strSQL, pValQuery);
			
			Vector<String> terms = new Vector<String>();

			terms.clear();
			for (int i = 0; i < colsUp.length; i++)
			{
				if (colsUp[i])
				{
					terms.add("contig.P_" + pValCols[i] + ">0 ");
				}
				else if (colsDown[i])
				{
					terms.add("contig.P_" + pValCols[i] + "<0 ");
				}
			}
			if (terms.size() >0)
			{
				String sql = Utils.strVectorJoin(terms, " and ");
				strSQL = appendANDPredicate(strSQL, sql);				
			}
		}
		if ( bFirstBest ) {
			String annoStr = "", temp = "";
			if(strAnnoTypeDB != null) {
				if(strAnnoTypeDB.length == 0) {
					strSQL = appendANDPredicate(strSQL, "contig.PIDov IS NULL");
				} else {
				
					for(int x=0; x<strAnnoTypeDB.length; x++) {
						temp = "(contig.PIDov=pja_db_unitrans_hits.PID AND pja_db_unitrans_hits.dbtype='" 
								+ strAnnoTypeDB[x].substring(0, strAnnoTypeDB[x].length()-2) 
								+ "' AND pja_db_unitrans_hits.taxonomy='" + strAnnoTaxoDB[x] + "')";
						if(annoStr.length() == 0)
							annoStr = temp;
						else
							annoStr = appendORPredicate(annoStr, temp);
					}
					strSQL = appendANDPredicate(strSQL, annoStr);
				}
			}
		} else {
			String annoStr = "", temp = "";
			if(strAnnoTypeDB != null) {
				if(strAnnoTypeDB.length == 0) {
					strSQL = appendANDPredicate(strSQL, "contig.PID IS NULL");
				} else {
					for(int x=0; x<strAnnoTypeDB.length; x++) {
						temp = "(contig.PID=pja_db_unitrans_hits.PID AND pja_db_unitrans_hits.dbtype='" 
								+ strAnnoTypeDB[x].substring(0, strAnnoTypeDB[x].length()-2) 
								+ "' AND pja_db_unitrans_hits.taxonomy='" + strAnnoTaxoDB[x] + "')";
						if(annoStr.length() == 0)
							annoStr = temp;
						else
							annoStr = appendORPredicate(annoStr, temp);
					}
					strSQL = appendANDPredicate(strSQL, annoStr);
				}
			}
		}		
		if ( StringHelpers.isEmpty( strSQL ) )
			return null;
		else
			return "(" + strSQL + ")";
		
	}
	
	private String getExcludePredicate ( )
	{
		String str = null;
		if ( nFilterHasNotes == FilterContigData.FILTER_EXCLUDE )
			str = appendORPredicate ( str, "contig.notes IS NOT NULL" );		
		if ( nFilterHasNs == FilterContigData.FILTER_EXCLUDE )
			str = appendORPredicate ( str, "contig.has_ns = TRUE" );		
		
		// Exclude contigs
		if ( excludeContigIDs != null && excludeContigIDs.size() > 0 )
		{
			str = appendORPredicate ( str, "contig.contigid IN ( '" + 
						StringHelpers.join( excludeContigIDs.iterator(), "', '" )  + "' ) " );
		}	

		return str;	
	}
	
	private static String appendPredicate ( String strPred1, int nType, String strPred2 )
	{
		if ( StringHelpers.isEmpty ( strPred1 ) )
			return strPred2;
		else if ( StringHelpers.isEmpty ( strPred2 ) )
			return strPred1;
		else if ( nType == FILTER_OR )
			return "( ( " + strPred1 + " ) OR ( " + strPred2 + " ) )";
		else if ( nType == FILTER_AND )
			return "( ( " + strPred1 + " ) AND ( " + strPred2 + " ) )";	
		throw new RuntimeException ( "Invalid AND/OR value of " + nType );
	}
	
	private static String appendANDPredicate ( String strPred1, String strPred2 )
	{
		return appendPredicate ( strPred1, FILTER_AND, strPred2 );
	}

	private static String appendORPredicate ( String strPred1, String strPred2 )
	{
		return appendPredicate ( strPred1, FILTER_OR, strPred2 );
	}
	
	//Sent null if all selected, if none selected pass empty array
	public String [] getAnnoTypeDB() { return strAnnoTypeDB; }
	public void setAnnoTypeDB(String [] types) {
		if(types==null) 
			strAnnoTypeDB = null;
		else {
			strAnnoTypeDB = new String[types.length];
			for(int x=0; x<types.length; x++)
				strAnnoTypeDB[x] = types[x];
		}
	}
	public String [] getAnnoTaxoDB() { return strAnnoTaxoDB; }
	public void setAnnoTaxoDB(String [] taxos) {
		if(taxos==null) 
			strAnnoTaxoDB = null;
		else {
			strAnnoTaxoDB = new String[taxos.length];
			for(int x=0; x<taxos.length; x++)
				strAnnoTaxoDB[x] = taxos[x];
		}
	}
	
	public boolean isPValFilter() { return bPValFilter; }
	public void setPValFilter(boolean useFilter) { bPValFilter = useFilter; }
	public boolean isPValBoolAND() { return bPValBoolAnd; }
	public void setPValBoolAND(boolean isAND) { bPValBoolAnd = isAND; }
	public double getPValLimit() { return dPValLimit; }
	public void setPValLimit(double limit) { dPValLimit = limit; }
	public String [] getSelectedPValColumns() { return pValCols; }
	public boolean [] getPValUpColumns() { return colsUp; }
	public boolean [] getPValDownColumns() { return colsDown; }
	public void setSelectedPValColumns(String [] selectedCols, boolean[] cUp, boolean cDown[]) {
		if(selectedCols == null) {
			pValCols = null; colsUp = null; colsDown = null;
			System.err.println("none!");
		}
		else {
			pValCols = new String[selectedCols.length];
			colsUp = new boolean[selectedCols.length];
			colsDown = new boolean[selectedCols.length];
			for(int x=0; x<selectedCols.length; x++) {
				pValCols[x] = selectedCols[x];
				colsUp[x] = cUp[x];
				colsDown[x] = cDown[x];
			}
		}
	}
	
	public boolean isCtgNumAligns() { return bCtgNumAligns; }
	public void setCtgNumAligns(boolean filterByNumAligns) { bCtgNumAligns = filterByNumAligns; }
	public boolean isCtgNumAlignsLT() { return bCtgNumAlignsLT; }
	public void setCtgNumAlignsLT(boolean numAlignsLT) { bCtgNumAlignsLT = numAlignsLT; }
	public int getCtgNumAligns() { return nCtgNumAligns; }
	public void setCtgNumAligns(int limit) { nCtgNumAligns = limit; }
	
	public boolean isCtgLength() { return bCtgLength; }
	public void setCtgLength(boolean filterByContigLength) { bCtgLength = filterByContigLength; }
	public boolean isCtgLengthLT() { return bCtgLengthLT; }
	public void setCtgLengthLT(boolean contigLengthLT) { bCtgLengthLT = contigLengthLT; }
	public int getCtgLength() { return nCtgLength; }
	public void setCtgLength(int limit) { nCtgLength = limit; }
	
	public boolean isCtgTotalExpLevel() { return bCtgTotalExpLevel; }
	public void setCtgTotalExpLevel(boolean filterByContigTotalExpLevel) { 
		bCtgTotalExpLevel = filterByContigTotalExpLevel; }
	public boolean isCtgTotalExpLevelLT() { return bCtgTotalExpLevelLT; }
	public void setCtgTotalExpLevelLT(boolean contigLengthLT) { bCtgTotalExpLevelLT = contigLengthLT; }
	public int getCtgTotalExpLevel() { return nCtgTotalExpLevel; }
	public void setCtgTotalExpLevel(int limit) { nCtgTotalExpLevel = limit; }	
	
	public void setFilterHasNs ( int n ) { nFilterHasNs = n; }
	public int getFilterHasNs ( ) { return nFilterHasNs; }
	
	public void setFilterHasNotes ( int n ) { nFilterHasNotes = n; }
	public int getFilterHasNotes ( ) { return nFilterHasNotes; }
	
	public boolean isDBHitLenLT() { return bDBHitLenLT; }
	public void setDBHitLenLT(boolean isSelected) { bDBHitLenLT = isSelected; }
	public boolean isDBHitLen() { return bDBHitLen; }
	public int  getDBHitLen() { return nDBHitLen; }
	public void setDBHitLen(boolean isSelected) { bDBHitLen = isSelected; }
	public void setDBHitLen(int length) { nDBHitLen = length; }
	
	public boolean isDBHitEvalLT() { return bDBHitEvalLT; }
	public void setDBHitEvalLT(boolean isSelected) { bDBHitEvalLT = isSelected; } 
	public boolean isDBHitEval() { return bDBHitEval; }
	public double getDBHitEval() { return dDBHitEval; }
	public void   setDBHitEval(boolean isSelected) { bDBHitEval = isSelected; }
	public void   setDBHitEval(double eVal) { dDBHitEval = eVal; }
	
	public boolean isDBHitBitScoreLT() { return bDBHitBitScoreLT; }
	public void setDBHitBestScoreLT(boolean isSelected) { bDBHitBitScoreLT = isSelected; }
	public boolean isDBHitBitScore() { return bDBHitBitScore; }
	public int  getDBHitBitScore() { return nDBHitBitScore; }
	public void setDBHitBitScore(boolean isSelected) { bDBHitBitScore = isSelected; }
	public void setDBHitBitScore(int bitScore) { nDBHitBitScore = bitScore; }

	public boolean isDBHitIdentityLT() { return bDBHitIdentLT; }
	public void setDBHitIdentityLT(boolean isSelected) { bDBHitIdentLT = isSelected; }
	public boolean isDBHitIdentity() { return bDBHitIdent; }
	public void setDBHitIdentity(boolean isSelected) { bDBHitIdent = isSelected; }
	public void setDBHitIdentity(int percentage) { nDBHitIdent = percentage; }
	public int getDBHitIdentity() { return nDBHitIdent; }
	
	public boolean hasAnnotation() { return bHasAnnotation; }
	public void setHasAnnotation(boolean isSelected) { bHasAnnotation = isSelected; }
	public boolean hasNoAnnotation() { return bNoAnnotation; }
	public void setNoAnnotation(boolean anno) { bNoAnnotation = anno; }
	public boolean hasEitherAnnotation() { return bEitherAnnotation; }
	public void setEitherAnnotation(boolean anno) { bEitherAnnotation = anno; }
	public int getDBHitAndOr() { return nDBHitAndOr; }
	public void setDBHitAndOr(int DBHitAndOr) { nDBHitAndOr = DBHitAndOr; }
	public boolean isFirstBestSelected() { return bFirstBest; }
	public void setFirstBestSelected(boolean selected) { bFirstBest = selected; }

	public int getORFMinNT() { return nORFMinNT; }
	public void setORFMinNT(int codingMin) { nORFMinNT = codingMin; }
	
	public boolean isBothUTRs() { return bBothUTRs; }
	public void setBothUTRs(boolean bothUTRs) { bBothUTRs = bothUTRs; }
	
	public boolean isProteinORF() { return bProteinORF; }
	public void setProteinORF(boolean b) { bProteinORF= b; }
	
	public Vector<String> getExcludeContigIDs() { return excludeContigIDs; }

	/**
	 * Set the contig IDs to exclude and clear the include contig IDs
	 * @param excludeContigIDs vector of contigs to exclude
	 */
	public void setExcludeContigIDs(Vector<String> excludeContigIDs) {
		this.excludeContigIDs = excludeContigIDs;
		includeContigIDs.removeAllElements();
	}

	public Vector<String> getIncludeContigIDs() { return includeContigIDs; }

	/**
	 * Set the contig IDs to include and clear the exclude contig IDs
	 */
	public void setIncludeContigIDs(Vector<String> includeContigIDs) {
		this.includeContigIDs = includeContigIDs;
		excludeContigIDs.removeAllElements();
	}		
	
	public Vector<String> getIncludeUniProtIDs() { return includeUniProtIDs; }
	public void setIncludeUniProtIDs(Vector<String> includeUniProtIDs) { this.includeUniProtIDs = includeUniProtIDs; }

	public Vector<String> getIncludeCloneIDs() { return includeCloneIDs; }
	public void setIncludeCloneIDs(Vector<String> includeCloneIDs) { this.includeCloneIDs = includeCloneIDs; }

	public boolean isORFCoding() { return bORFCoding; }
	public void setORFCoding(boolean coding) { bORFCoding = coding; }
	
	public boolean isGOID() { return bGOID; }
	public void setGOID(boolean state) { bGOID = state; }
	
	public String getGOID() { return strGOID; }
	public void setGOID(String id) { strGOID = id; }
	/**
	 * @return the contigs that are either included or excluded
	 */
	public String getContigIDFilterDescription() {
		int MAX_TO_LIST = 2;
		
		if (excludeContigIDs != null) {
			if (excludeContigIDs.size() > MAX_TO_LIST) {
				return "Exclude: " + excludeContigIDs.size() + " contigs";
			} 
			else if (excludeContigIDs.size() > 0) {
				return "Exclude: "
						+ StringHelpers.join(excludeContigIDs.iterator(), ", ");
			}
		}

		if (includeContigIDs != null) {
			if (includeContigIDs.size() > MAX_TO_LIST) {
				return "Include only: " + includeContigIDs.size() + " contigs";
			} 
			else if (includeContigIDs.size() > 0) {
				return "Include only: "
						+ StringHelpers.join(includeContigIDs.iterator(), ", ");
			}
		}

		return "Include: all";
	}

	public boolean isLibrarySelected() { return bNumIncLibrary || bNumExLibrary || bNFoldLibrary; }
	public boolean isNumIncLibrary() { return bNumIncLibrary; }
	public void setNumIncLibrary(boolean val) { bNumIncLibrary = val; }
	public boolean isNumExLibrary() { return bNumExLibrary; }
	public void setNumExLibrary(boolean val) { bNumExLibrary = val; }
	public boolean isNFoldLibrary() { return bNFoldLibrary; }
	public void setNFoldLibrary(boolean val) { bNFoldLibrary = val; }
	
	public String [] getAllRequiredLibs(FieldTab fTab) { 
		Vector<String> retVal = new Vector<String> ();
		
		if(selectedIncLibs != null) {
			for(int x=0; x<selectedIncLibs.length; x++)
				if(!retVal.contains(selectedIncLibs[x]))
					retVal.add(selectedIncLibs[x]);
		}

		if(selectedExLibs != null) {
			for(int x=0; x<selectedExLibs.length; x++)
				if(!retVal.contains(selectedExLibs[x]))
					retVal.add(selectedExLibs[x]);
		}
		
		String [] foldCols = fTab.getFoldColumns();
		for(int x=0; x<foldCols.length; x++) {
			String [] vals = foldCols[x].split("/");
			if(!retVal.contains(vals[0]))
				retVal.add(vals[0]);
			if(!retVal.contains(vals[1]))
				retVal.add(vals[1]);
		}
		
		return retVal.toArray(new String[0]);
	}
	public String [] getIncludeLibs() { return selectedIncLibs; }
	public void setIncludeLibs(String [] libs) {
		if(libs == null) selectedIncLibs = null;
		else {
			selectedIncLibs = new String[libs.length];
			for(int x=0; x<libs.length; x++)
				selectedIncLibs[x] = libs[x];
		}
	}
	public String [] getExcludeLibs() { return selectedExLibs; }
	public void setExcludeLibs(String [] libs) { 
		if(libs == null) selectedExLibs = null;
		else {
			selectedExLibs = new String[libs.length];
			for(int x=0; x<libs.length; x++)
				selectedExLibs[x] = libs[x];
		}
	}
	public double getIncLibsCount() { return dNumIncLibs; }
	public void setIncLibsCount(double val) { dNumIncLibs = val; }
	public double getExLibsCount() { return dNumExLibs; }
	public void setExLibsCount(double val) { dNumExLibs = val; }
	public double getNFoldLibs() { return dNFoldLibCount; }
	public void setNFoldLibs(double val) { dNFoldLibCount = val; }
	
	public boolean isIncLibsCountAnd() { return bNumIncLibsAnd; }
	public void setIncLibsCountAnd(boolean val) { bNumIncLibsAnd = val; }
	public boolean isExLibsCountAnd() { return bNumExLibsAnd; }
	public void setExLibsCountAnd(boolean val) { bNumExLibsAnd = val; }
	public boolean isNFoldIncAnd() { return bNFoldIncAnd; }
	public void setNFoldIncAnd(boolean val) { bNFoldIncAnd = val; }
	public int getFoldRange() { return nFoldRange; }
	public void setFoldRange(int range) { nFoldRange = range;}
	public boolean isNFoldExAnd() { return bNFoldExAnd; }
	public void setNFoldExAnd(boolean val) { bNFoldExAnd = val; } 
	public boolean isLibNormalized() { return bNormalizedMode; }
	public void setLibNormalized(boolean val) { bNormalizedMode = val; }
	
	private static final String ALL_CONTIGS_PRED = "( true )";
	
	public boolean isGtrEquSNPs() { return bGtrEquSNPs; }
	public void setGtrEquSNPs(boolean gtrEquSNPs) { bGtrEquSNPs = gtrEquSNPs; }
	public boolean isLessEquSNPs() { return bLessEquSNPs; }
	public void setLessEquSNPs(boolean lessEquSNPs) { bLessEquSNPs = lessEquSNPs; }
	public int getGtrEquSNPs() { return nGtrEquSNPs; }
	public void setGtrEquSNPs(int gtrEquSNPs) { nGtrEquSNPs = gtrEquSNPs; }
	public int getLessEquSNPs() { return nLessEquSNPs; }
	public void setLessEquSNPs(int lessEquSNPs) { nLessEquSNPs = lessEquSNPs; }
	
	/**
	 * Clear memory associated with the object
	 */
	public void clear()
	{
		if(excludeContigIDs != null) excludeContigIDs.clear();
		if(includeContigIDs != null) includeContigIDs.clear();
		if(includeCloneIDs != null) includeCloneIDs.clear();
		if(includeUniProtIDs != null) includeUniProtIDs.clear();
	}
	
	private int nFilterHasNs = FilterContigData.FILTER_NONE;
	private int nFilterHasNotes = FilterContigData.FILTER_NONE;
	
	private boolean bCtgNumAligns = false;
	private boolean bCtgNumAlignsLT = false;
	private int 	nCtgNumAligns = 1;
	
	private boolean bCtgLength = false;
	private boolean bCtgLengthLT = false;
	private int 	nCtgLength = 1;
	
	private boolean bCtgTotalExpLevel = false;
	private boolean bCtgTotalExpLevelLT = false;
	private int 	nCtgTotalExpLevel = 1;
	
	private boolean bGtrEquSNPs = false;
	private int nGtrEquSNPs = 1; 
	private boolean bLessEquSNPs = false;	
	private int nLessEquSNPs = 1;
	
	private boolean bORFCoding = false;
	private int nORFMinNT = 300;
	private boolean bProteinORF = false;
	private boolean bBothUTRs = false;
	
	private boolean bGOID = false;
	private String strGOID = "";
	
	private boolean bHasAnnotation = false;
	private boolean bNoAnnotation = false;
	private boolean bEitherAnnotation = false;
	private boolean bFirstBest = false;
	private int nDBHitAndOr = FILTER_AND;
	
	private boolean bPValFilter = false;
	private boolean bPValBoolAnd = false;
	private double dPValLimit = 1;
	private String [] pValCols = null;
	private boolean [] colsUp = null;
	private boolean [] colsDown = null;

	private boolean bDBHitLen = false;
	private boolean bDBHitLenLT = false;
	private int nDBHitLen = 100;
	
	private boolean bDBHitEval = false;
	private boolean bDBHitEvalLT = true;
	private double dDBHitEval = 1e-30;
	
	private boolean bDBHitBitScore = false;
	private boolean bDBHitBitScoreLT = false;
	private int nDBHitBitScore = 300;
	
	private boolean bDBHitIdent = false;
	private boolean bDBHitIdentLT = false;
	private int nDBHitIdent = 0;
		
	//store library filter info
	private String [] selectedIncLibs = null;
	private String [] selectedExLibs = null;
	private double dNumIncLibs = 1, dNumExLibs = 0, dNFoldLibCount = 2; 
	private int nFoldRange = 0;
	private boolean bNumIncLibsAnd, bNumExLibsAnd, bNFoldIncAnd, bNFoldExAnd;
	private boolean bNormalizedMode = true;
	private boolean bNumIncLibrary = false, bNumExLibrary = false, bNFoldLibrary = false;
	
	//store anno information
	private String [] strAnnoTypeDB = null;
	private String [] strAnnoTaxoDB = null;
	
	private Vector<String> excludeContigIDs = new Vector<String> ();
	private Vector<String> includeContigIDs = new Vector<String> ();
	private Vector<String> includeCloneIDs  = new Vector<String> (); 
	private Vector<String> includeUniProtIDs = new Vector<String> (); 

    private static final long serialVersionUID = 1;
}
